Skip to content

Conversation

@DavideD
Copy link
Member

@DavideD DavideD commented Nov 18, 2025

Fix #2768

Follows #2690 and it's a refactoring of @tsegismont suggestion.

  • I changed the warning about the swithching context into assertions
  • I had to change where we read the context when a new connection is created. The problem is that the session factory can be used in a worker thread at start up, and therefore the context could be null. This is the line that saves the context
  • ProxyConnection synchronize the creation of a connection using reflection. I don't know if this can be a problem with Quarkus.

@DavideD DavideD requested a review from yrodiere November 19, 2025 11:50
@DavideD DavideD added this to the 4.2.0.Beta1 milestone Nov 19, 2025
Copy link
Member

@yrodiere yrodiere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DavideD DavideD force-pushed the 2768-Connection-context branch from e4fdfd4 to 9dce31a Compare November 19, 2025 17:42
For now we use it only when the connection is used
@DavideD DavideD force-pushed the 2768-Connection-context branch from 9dce31a to 5c245f9 Compare November 26, 2025 11:18
This commit:

* Stop connection leaks in BlockingIdentifierGenerator
* Assert that the connection is used in the expected context
@DavideD DavideD force-pushed the 2768-Connection-context branch from 5c245f9 to 6b31752 Compare November 26, 2025 14:46
@DavideD
Copy link
Member Author

DavideD commented Nov 26, 2025

I should have addressed all the comments. If CI doens't fail, I'm going to merge this so that I can start the release.
If there's something else to change, we can address it later.

Thanks a lot!

@DavideD DavideD force-pushed the 2768-Connection-context branch from 37a5dda to f7438b9 Compare November 26, 2025 15:28
Copy link
Member

@yrodiere yrodiere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @DavideD , LGTM!

Comment on lines +407 to +409
if ( connectionFuture.isDone() ) {
// connection exists, we can let callers use the delegate and forget about the proxy.
return connectionFuture.getNow( null ).withBatchSize( batchSize );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the pattern if ( ... .isDone() ) { get() } should be avoided in general, because it's sensitive to TOCTOU. That's why I suggested var value = getNow(null); if ( value != null) .

Though in this case... I think the worst that could happen is a missed opportunity, so it's probably fine.

Copy link
Member Author

@DavideD DavideD Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm afraid of using getNow(null) in this case, it's that we will return null a bit too soon.

In this specific case, when .isDone() returns true, we should know for a fact that there's a result that we can return.

When it returns false, it's possible that by the time we call .getNow(null), the result is not null and we have created a ProxyConnection even if we didn't need to, but my guess is that this use case won't happen often.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though in this case... I think the worst that could happen is a missed opportunity, so it's probably fine.

I didn't notice this line. Yes, that's what I was thinking.
The initial solution could have potentially caused a NullPointerException instead.

}
else {
connection = connection.withBatchSize( batchSize );
return new ProxyConnection( () -> opened
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the opened check here is supposed to handle a case where someone does something like this?

<trigger connection request>
connection = connection.withBatchSize(...); // Connection not yet initialized somehow?
connection.doSomething();

That seems odd... did you do this because you noticed it actually happening?

In any case, +1 to be on the safe side.

Copy link
Member Author

@DavideD DavideD Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's to be on the safe side.

Looking at the code, it seems to me there's a small window between setting opened to true and completing completableFuture with the connection. So, if opened it's true and completableFuture is not done, .getNow(null) will return null (and cause a NullPointerException), even if the connection is getting opened.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit late, I think I will sleep over it and merge it tomorrow morning if there are no other comments.
After that I will start the release.

Thanks

Now we test with and without transactions.
And the test will throw an exception if context and connections
aren't handled correctly.
@DavideD DavideD force-pushed the 2768-Connection-context branch from f7438b9 to 01ebf2c Compare November 26, 2025 17:35
@DavideD DavideD merged commit ef1e647 into hibernate:main Nov 27, 2025
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A connection can be opened in the wrong Context

3 participants